package cn.edu.hit.education.action;

import java.io.IOException;
import java.util.List;
import java.util.Map;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.eclipse.jface.action.Action;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.plugin.AbstractUIPlugin;

import cn.edu.hit.education.pojo.Course;
import cn.edu.hit.education.pojo.Property;
import cn.edu.hit.education.pojo.Specialty;
import cn.edu.hit.education.pojo.User;
import cn.edu.hit.education.service.ICourseService;
import cn.edu.hit.education.service.IPropertyService;
import cn.edu.hit.education.service.ISpecialtyService;
import cn.edu.hit.education.service.IUserSpeciatyService;
import cn.edu.hit.education.service.PropertyServiceImpl;
import cn.edu.hit.education.service.SpecialtyServiceImpl;
import cn.edu.hit.education.service.UserSpeciatyServiceImpl;
import cn.edu.hit.education.utils.ExcelUtil;
import educationschedule.Activator;
import educationschedule.Application;

/**
 * 导入课程，如果重复且更新，则覆盖原有课程，如果重复无更新，不做任何操作！没有则新增一条数据。
 * <p>
 * Title: ImportAction
 * </p>
 * <p>
 * Description:
 * </p>
 * 
 * @author 罗成
 * @date 2021年5月9日
 */
public class ImportAction extends Action {
	ICourseService courseService = (ICourseService) Application.applicationContext
			.getBean("courseServiceImpl");
	IUserSpeciatyService userSpeciatyService = Application.applicationContext
			.getBean(UserSpeciatyServiceImpl.class);
	ISpecialtyService specialtyService = Application.applicationContext
			.getBean(SpecialtyServiceImpl.class);
	IPropertyService propertyService = Application.applicationContext
			.getBean(PropertyServiceImpl.class);

	private List<Integer> speciatyids = null;

	public ImportAction() {
		this.setImageDescriptor(AbstractUIPlugin.imageDescriptorFromPlugin(
				Activator.PLUGIN_ID, "icons/toolbar/import_16px.png"));
		this.setToolTipText("导入课程");
		this.setText("导出课程");
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		Shell parentShell = PlatformUI.getWorkbench()
				.getActiveWorkbenchWindow().getShell();
		FileDialog fileDialog = new FileDialog(parentShell, SWT.OPEN);
		fileDialog.setFilterExtensions(new String[] { "*.xls" });
		String filename;
		filename = fileDialog.open();
		if (filename != null) {
			try {
				read(filename);
				MessageBox messageBox=new MessageBox(parentShell,SWT.OK|SWT.ICON_INFORMATION);
				 messageBox.setText("提示");
				 messageBox.setMessage("导入成功！");
				 messageBox.open();
			} catch (IOException e) {
				MessageBox messageBox=new MessageBox(parentShell,SWT.OK|SWT.ICON_INFORMATION);
				 messageBox.setText("导入失败！！");
				 messageBox.setMessage("原因：导入异常！"  );
				 messageBox.open();
			} catch(NumberFormatException e ){
				MessageBox messageBox=new MessageBox(parentShell,SWT.OK|SWT.ICON_INFORMATION);
				 messageBox.setText("部分课程信息未能导入！");
				 messageBox.setMessage("原因：课程信息不允许留空！请修改表格后重新导入！"  );
				 messageBox.open();
			}catch(RuntimeException e){
				MessageBox messageBox=new MessageBox(parentShell,SWT.OK|SWT.ICON_INFORMATION);
				 messageBox.setText("导入失败！！");
				 messageBox.setMessage("原因：" + e.getMessage());
				 messageBox.open();
			}
		}
		super.run();
	}
	
	/**
	 * xls表格导入
	 * <p>Title: read</p>  
	 * <p>Description: </p>  
	 * @param filename
	 * @throws IOException
	 */
	public void read(String filename) throws IOException {
		Subject subject = SecurityUtils.getSubject();
		// 根据普通用户的用户Id查询到关联的专业Id (只能操作修改本专业下课程，避免覆盖其他专业同名课程)
		User user = (User) subject.getPrincipal();
		speciatyids = userSpeciatyService.querySpeciatyIdsByUser(user.getId());
		List<Course> courseFromDb = courseService
				.queryAllCourseBySpecityId(speciatyids);

		ExcelUtil excel = new ExcelUtil();
		List<Map<String, Object>> listmap = excel.readExcel(filename);
		if (listmap != null) {
			for (Map<String, Object> map : listmap) {
				boolean hasEquals = false;
				for (Course course : courseFromDb) {
					String nameFromEx = (String) map.get("课程名称");
					String nameFromDb = course.getName();
					//课程名称相同，再判断其他值是否全部相同
					if (nameFromEx.equals(nameFromDb)) {
						
						//从Excel获取的数据封装为Course对象,
						Course courseFroEx = courseMapToObj(map);
						//重写的equals方法，避免多次覆盖数据库数据，造成多次IO导致系统慢
						if(course.equals(courseFroEx)){
							System.out.println("数据一致，不用修改！");
							hasEquals = true;
							break;
						}
						
						updateCourse(course.getId(), map);
						System.out.println("修改了数据库！");
						hasEquals = true;
						break;
					} 
				}
				String nameFromEx = (String) map.get("课程名称");
				if("".equals(nameFromEx)){
					return;
				}
				if(hasEquals == false){
					insertCourse(map);
				}

			}
		}

	}
	
	/**
	 * 增加一门课程
	 * <p>Title: insertCourse</p>  
	 * <p>Description: </p>  
	 * @param coursemMap
	 */
	private void insertCourse(Map<String, Object> coursemMap) {
		Course course = new Course();
		Specialty specialty = specialtyService.queryByPrimaryKey(speciatyids
				.get(0));// 一个教研主任只负责一个专业的增删改，默认取用户拥有权限的第一个专业id

		// 如果添加课程的专业与用户权限不符，导入失败抛出异常
		String nameFromEx = (String) coursemMap.get("专业名称");
		String nameFromDb = specialty.getName();
		if (!nameFromEx.equals(nameFromDb)) {
			throw new RuntimeException("只能为" + specialty.getName() + "添加课程！");
		} else {
			
			// 设置专业Id
			course.setSpecialtyId(speciatyids.get(0));

			// 设置课程性质Id
			Property property = propertyService.queryPropertyByName(String
					.valueOf(coursemMap.get("课程性质")));
			if (property != null) {

				course.setPropertyId(property.getId());
			}

			// 设置课程名称
			course.setName(String.valueOf(coursemMap.get("课程名称")));

			// 设置课程学分
			course.setCredits(Double.valueOf((String) coursemMap.get("课程学分")));

			// 设置是否核心
			course.setImportant(coursemMap.get("是否核心").equals("是") ? 1 : 0);

			// 设置课程编号
			course.setNumber((String) coursemMap.get("课程编号"));

			// 设置课程学时
			course.setPeriod(Double.valueOf((String) coursemMap.get("课程学时")));

			// 设置理论学时
			course.setTheoretical(Double.valueOf((String) coursemMap
					.get("理论学时")));
			// 设置实验学时

			course.setExperiment(Double.valueOf((String) coursemMap.get("实验学时")));

			// 学时单位
			course.setUnit((String) coursemMap.get("实验学时"));

			// 设置课程选修

			course.setSelected((String) coursemMap.get("课程选修"));

			// 设置授课类型

			course.setMethod((String) coursemMap.get("授课类型"));
			// 设置授课方式
			course.setClassroom((String) coursemMap.get("授课方式"));
			// 设置开始时间

			course.setStart(Integer.valueOf((String) coursemMap.get("开始时间")));

			// 设置结束时间
			course.setEnd(Integer.valueOf((String) coursemMap.get("结束时间")));
			// 设置课程备注
			course.setNote((String) coursemMap.get("课程备注"));

			int insert = courseService.insert(course);

			System.out.println("插入成功！");

		}

	}
	
	/**
	 * 接受来自Excel的每一个map，封装成CourseTo对象
	 * <p>Title: courseMapToObj</p>  
	 * <p>Description: </p>  
	 * @param coursemMap
	 * @return
	 */
	public Course courseMapToObj(Map<String, Object> coursemMap){
		Course course = new Course();
		Specialty specialty = specialtyService.queryByPrimaryKey(speciatyids
				.get(0));// 一个教研主任只负责一个专业的增删改，默认取用户拥有权限的第一个专业id

		// 如果添加课程的专业与用户权限不符，导入失败抛出异常
		String nameFromEx = (String) coursemMap.get("专业名称");
		String nameFromDb = specialty.getName();
		if (!nameFromEx.equals(nameFromDb)) {
			throw new RuntimeException("只能为" + specialty.getName() + "添加课程！");
		} else {
			// 设置专业Id
			course.setSpecialtyId(speciatyids.get(0));

			// 设置课程性质Id
			Property property = propertyService.queryPropertyByName(String
					.valueOf(coursemMap.get("课程性质")));
			if (property != null) {

				course.setPropertyId(property.getId());
			}

			// 设置课程名称
			course.setName(String.valueOf(coursemMap.get("课程名称")));

			// 设置课程学分
			course.setCredits(Double.valueOf((String) coursemMap.get("课程学分")));

			// 设置是否核心
			course.setImportant(coursemMap.get("是否核心").equals("是") ? 1 : 0);

			// 设置课程编号
			course.setNumber((String) coursemMap.get("课程编号"));

			// 设置课程学时
			course.setPeriod(Double.valueOf((String) coursemMap.get("课程学时")));

			// 设置理论学时
			course.setTheoretical(Double.valueOf((String) coursemMap
					.get("理论学时")));
			// 设置实验学时

			course.setExperiment(Double.valueOf((String) coursemMap.get("实验学时")));

			// 学时单位
			course.setUnit((String) coursemMap.get("实验学时"));

			// 设置课程选修

			course.setSelected((String) coursemMap.get("课程选修"));

			// 设置授课类型

			course.setMethod((String) coursemMap.get("授课类型"));
			// 设置授课方式
			course.setClassroom((String) coursemMap.get("授课方式"));
			// 设置开始时间

			course.setStart(Integer.valueOf((String) coursemMap.get("开始时间")));

			// 设置结束时间
			course.setEnd(Integer.valueOf((String) coursemMap.get("结束时间")));
			// 设置课程备注
			course.setNote((String) coursemMap.get("课程备注"));
	
		}
		
		
		return course;
		
	}
	
	/**
	 * 更新或覆盖一门课程！
	 * <p>Title: updateCourse</p>  
	 * <p>Description: </p>  
	 * @param id
	 * @param coursemMap
	 */
	private void updateCourse(Integer id, Map<String, Object> coursemMap) {
		// TODO Auto-generated method stub
		Course course = new Course();
		Specialty specialty = specialtyService.queryByPrimaryKey(speciatyids
				.get(0));// 一个教研主任只负责一个专业的增删改，默认取用户拥有权限的第一个专业id

		// 如果添加课程的专业与用户权限不符，导入失败抛出异常
		String nameFromEx = (String) coursemMap.get("专业名称");
		String nameFromDb = specialty.getName();
		if (!nameFromEx.equals(nameFromDb)) {
			throw new RuntimeException("只能为" + specialty.getName() + "添加课程！");
		} else {
			// 设置专业Id
			course.setSpecialtyId(speciatyids.get(0));

			// 设置课程性质Id
			Property property = propertyService.queryPropertyByName(String
					.valueOf(coursemMap.get("课程性质")));
			if (property != null) {

				course.setPropertyId(property.getId());
			}

			// 设置课程名称
			course.setName(String.valueOf(coursemMap.get("课程名称")));

			// 设置课程学分
			course.setCredits(Double.valueOf((String) coursemMap.get("课程学分")));

			// 设置是否核心
			course.setImportant(coursemMap.get("是否核心").equals("是") ? 1 : 0);

			// 设置课程编号
			course.setNumber((String) coursemMap.get("课程编号"));

			// 设置课程学时
			course.setPeriod(Double.valueOf((String) coursemMap.get("课程学时")));

			// 设置理论学时
			course.setTheoretical(Double.valueOf((String) coursemMap
					.get("理论学时")));
			// 设置实验学时

			course.setExperiment(Double.valueOf((String) coursemMap.get("实验学时")));

			// 学时单位
			course.setUnit((String) coursemMap.get("实验学时"));

			// 设置课程选修

			course.setSelected((String) coursemMap.get("课程选修"));

			// 设置授课类型

			course.setMethod((String) coursemMap.get("授课类型"));
			// 设置授课方式
			course.setClassroom((String) coursemMap.get("授课方式"));
			// 设置开始时间

			course.setStart(Integer.valueOf((String) coursemMap.get("开始时间")));

			// 设置结束时间
			course.setEnd(Integer.valueOf((String) coursemMap.get("结束时间")));
			// 设置课程备注
			course.setNote((String) coursemMap.get("课程备注"));

			// 设置couseId
			course.setId(id);

			int update = courseService.update(course);
			System.out.println("修改成功！");

		}

	}

}
